package com.itheima.utils;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.common.DefaultException;
import com.itheima.convert.OrganizationConvert;
import com.itheima.convert.UserConvert;
import com.itheima.entity.Organization;
import com.itheima.entity.User;
import com.itheima.enums.OrganizationEnum;
import com.itheima.enums.RedisEnum;
import com.itheima.service.OrganizationService;
import com.itheima.service.UserService;
import com.itheima.vo.BriefUserVo;
import com.itheima.vo.organization.OrganizationVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 生成组织树状关系工具类
 *
 * @author 51585
 */
@Component
public class OrganizationTreeUtil {

    @Resource
    private OrganizationService organizationService;
    @Resource
    private UserService userService;
    @Resource
    private OrganizationConvert organizationConvert;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private UserConvert userConvert;

    /**
     * 返回完整的组织结构
     *
     * @return
     */
    public OrganizationVo create() {
        LambdaQueryWrapper<Organization> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Organization::getParentId, 0);
        Organization root = organizationService.getOne(lambdaQueryWrapper);
        OrganizationVo organizationVo = organizationConvert.organizationToOrganizationVo(root);
        supplyUsers(organizationVo);
        OrganizationVo res = getChild(organizationVo);
        redisTemplate.opsForValue().set(RedisEnum.ORGANIZATION_STRUCTURE_COMPLETE.getRedis(), JSONUtil.toJsonStr(res));
        return res;
    }

    /**
     * 获取子组织
     *
     * @param organizationVo
     * @return
     */
    public OrganizationVo getChild(OrganizationVo organizationVo) {
        if (organizationVo.getIsChild() == 1) {
            return null;
        }
        LambdaQueryWrapper<Organization> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Organization::getParentId, organizationVo.getId());
        List<Organization> list = organizationService.list(lambdaQueryWrapper);
        List<OrganizationVo> collect = list.stream().map(organization -> {
            OrganizationVo organizationVoMid = organizationConvert.organizationToOrganizationVo(organization);
            supplyUsers(organizationVoMid);
            getChild(organizationVoMid);
            return organizationVoMid;
        }).collect(Collectors.toList());

        organizationVo.setChildren(collect);

        return organizationVo;
    }

    public void supplyUsers(OrganizationVo organizationVo) {
        List<User> userList = userService.lambdaQuery()
                .select(User::getId, User::getName, User::getImageUrl)
                .eq(User::getOrganizationId, organizationVo.getId())
                .list();
        List<BriefUserVo> briefUserVos = userConvert.userToBriefUserVo(userList);
        organizationVo.setUserList(briefUserVos);
    }

    /**
     * 获取特定组织的子组织结构
     *
     * @param organizationId
     * @return
     */
    public OrganizationVo createByOrganization(int organizationId) throws DefaultException {
        Organization root = organizationService.lambdaQuery()
                .eq(Organization::getId, organizationId)
                .isNull(Organization::getDeletedAt)
                .one();
        Optional.ofNullable(root).orElseThrow(() -> new DefaultException("没有当前组织"));
        OrganizationVo organizationVo = organizationConvert.organizationToOrganizationVo(root);
        supplyUsers(organizationVo);
        if (organizationVo.getIsChild() == 1) {
            return organizationVo;
        }
        OrganizationVo res = getChild(organizationVo);
        redisTemplate.opsForValue().set(RedisEnum.ORGANIZATION_STRUCTURE.getRedis() + organizationId, JSONUtil.toJsonStr(res));
        return res;
    }


    /**
     * 获取传入组织id的所有父级组织
     * 用于展示所在组织的层级关系
     *
     * @param organizationId
     * @return
     */
    public List<String> getParentOrganization(int organizationId) {
        buildMap();
        List<String> res = new ArrayList<>();
        getParent(res, organizationId);
        redisTemplate.opsForValue().set(RedisEnum.ORGANIZATION_PARENT.getRedis() + organizationId, JSONUtil.toJsonStr(res));
        return res;
    }

    public void getParent(List<String> res, int organizationId) {
        Map<Integer, String> map = buildMap();
        if (organizationId == OrganizationEnum.school.getOrganizationId() || organizationId == OrganizationEnum.administrators.getOrganizationId()) {
            res.add(map.get(organizationId));
            return;
        }
        Organization organization = organizationService.lambdaQuery()
                .select(Organization::getParentId)
                .eq(Organization::getId, organizationId)
                .one();
        getParent(res, organization.getParentId());
        res.add(map.get(organizationId));
    }

    public Map<Integer, String> buildMap() {
        Map<Integer, String> map;
        List<Organization> list = organizationService.lambdaQuery()
                .select(Organization::getId, Organization::getName)
                .isNull(Organization::getDeletedAt)
                .list();
        map = new HashMap<>(list.size());
        list.forEach(k -> map.put(k.getId(), k.getName()));
        return map;
    }

}
